package com.ala4.oxcafe.boot.filter;

import com.ala4.oxcafe.boot.provider.WeChatAuthenticationToken;
import com.ala4.oxcafe.constants.SecurityConstants;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Setter;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
 * 微信登录拦截器-这里就是拦截微信登录的端点
 * 使用微信的code登录
 *
 * @author PING
 * @date 2025/8/11 21:58
 */
@Setter
public class WeChatAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    private static final RequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER;

    static {
        DEFAULT_ANT_PATH_REQUEST_MATCHER = PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/wx-code-login");
    }

    private String weChatParameter = "weChatCode";

    protected WeChatAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }

    public WeChatAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
    }

    public WeChatAuthenticationFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {
        super(defaultFilterProcessesUrl, authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        // 需要是 POST 请求
        if (!SecurityConstants.METHOD_POST.equals(request.getMethod())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        // json类型请求处理方式
        logger.debug("login ContentType " + request.getContentType());
        if (request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {
            WeChatAuthenticationToken authRequest = null;
            try (InputStream is = request.getInputStream()) {
                // 通过ObjectMapper读取request中的I/O流，将JSON映射到Map上
                Map<String, String> authenticationBean = objectMapper.readValue(is, new TypeReference<Map<String, String>>() {
                });

                // 获取微信code
                String weChatCode = authenticationBean.get(this.weChatParameter);

                authRequest = WeChatAuthenticationToken.unauthenticated(weChatCode);
            } catch (IOException e) {
                logger.error("WeChatAuthenticationFilter Error ", e);
                authRequest = new WeChatAuthenticationToken("");
            } catch (Exception e) {
                throw new AuthenticationServiceException(e.getMessage());
            }

            // Allow subclasses to set the "details" property
//            setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);

        } else {
            // 其他类型的请求依旧走原来的处理方式
            return super.attemptAuthentication(request, response);
        }
    }
}
